package com.xjj.core.modules.orm.hibernate;

import static org.hibernate.EntityMode.POJO;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.beanutils.PropertyUtils;

import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Example.PropertySelector;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import com.xjj.core.modules.commons.utils.MyBeanUtils;
import com.xjj.core.modules.commons.utils.ReflectionUtils;
import com.xjj.core.modules.orm.Condition;
import com.xjj.core.modules.orm.Finder;
import com.xjj.core.modules.orm.Nullable;
import com.xjj.core.modules.orm.OrderBy;
import com.xjj.core.modules.orm.Page;
import com.xjj.core.modules.orm.PageRequest;
import com.xjj.core.modules.orm.Updater;


/**
 * Hibernate的范型基类.
 * 
 * 可以在service类中直接创建使用.也可以继承出DAO子类,在多个Service类中共享DAO操作.
 * 参考Spring2.5自带的Petlinc例子,取消了HibernateTemplate,直接使用Hibernate原生API.
 * 通过Hibernate的sessionFactory.getCurrentSession()获得session,.
 * 
 * @param <T> DAO操作的对象类型
 * @param <PK> 主键类型
 * 
 * @author calvin
 */
@SuppressWarnings("unchecked")
public class SimpleHibernateTemplate<T, PK extends Serializable> {

	protected Logger logger = LoggerFactory.getLogger(getClass());

	protected SessionFactory sessionFactory;

	protected Class<T> entityClass;

	public SimpleHibernateTemplate(final SessionFactory sessionFactory, final Class<T> entityClass) {
		this.sessionFactory = sessionFactory;
		this.entityClass = entityClass;
	}

	public Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public void save(final T entity) {
		Assert.notNull(entity);
		getSession().saveOrUpdate(entity);
		logger.debug("save entity: {}", entity);
	}

	//lqz 增加 jeecms 来自：com.ponyjava.common.hibernate3.BaseDaoImpl
	//修改参数:原Object entity
	public Object merge(final T entity) {
		Assert.notNull(entity);
		return getSession().merge(entity);
	}

	public void delete(final T entity) {
		Assert.notNull(entity);
		getSession().delete(entity);
		logger.debug("delete entity: {}", entity);
	}

	public void delete(final PK id) {
		Assert.notNull(id);
		delete(get(id));
	}
	//lqz 增加 jeecms 来自：com.ponyjava.common.hibernate3.BaseDaoImpl
	//修改参数:原Serializable id --->final PK id
	//修改的过来的方法一定存在问题，要进行测试和再进行修改
	public T load(final PK id) {
		Assert.notNull(id);
		return load(id, false);
	}
	//lqz 增加 jeecms 来自：com.ponyjava.common.hibernate3.BaseDaoImpl
	//修改参数:原Serializable id --->final PK id
	//   boolean lock ---- >final boolean lock
	//getPersistentClass --->entityClass
	//修改的过来的方法一定存在问题，要进行测试和再进行修改
	@SuppressWarnings("unchecked")
	public T load(final PK id, final boolean lock) {
		Assert.notNull(id);
		T entity = null;
		if (lock) {
			entity = (T) getSession().load(entityClass, id,
					LockMode.UPGRADE);
		} else {
			entity = (T) getSession().load(entityClass, id);
		}
		return entity;
	}

	public List<T> findAll() {
		return findByCriteria();
	}

	public Page<T> findAll(final Page<T> page) {
		return findByCriteria(page);
	}
	//下面两个findAll方法来自jeecms
	//参数修改：原OrderBy... orders--->final OrderBy... orders
	//同时要增加：OrderBy 类
	@SuppressWarnings("unchecked")
	public List<T> findAll(final OrderBy... orders) {
		Criteria crit = createCriteria();
		if (orders != null) {
			for (OrderBy order : orders) {
				crit.addOrder(order.getOrder());
			}
		}
		return crit.list();
	}
	//下面两个findAll方法来自jeecms
	//参数修改：int pageNo, int pageSize ----> final int pageNo, final int pageSize,
	//原OrderBy... orders--->final OrderBy... orders
	//同时要增加findByCriteria方法
	//修改Pagination类 ---> Page<T>类
	public Page<T> findAll(final int pageNo, final int pageSize,final OrderBy... orders) {
		Criteria crit = createCriteria();
		return findByCriteria(crit, pageNo, pageSize, null, OrderBy
				.asOrders(orders));
	}
	//为上面的查询增加这个方法---protected类型为public
	//参数修改：前面全部增加final
	//修改Pagination类 ---> Page类
	@SuppressWarnings("unchecked")
	public Page<T> findByCriteria(final Criteria crit,final int pageNo,
			int pageSize, Projection projection, Order... orders) {
		int totalCount = (Integer) crit.setProjection(Projections.rowCount())
				.uniqueResult();
		//在Page中增加Page(pageNo, pageSize, totalCount)构造函数
		Page p = new Page(pageNo, pageSize, totalCount);
		if (totalCount < 1) {
			//p.setList--->p.setResult
			p.setResult(new ArrayList());
			return p;
		}
		crit.setProjection(projection);
		if (projection == null) {
			crit.setResultTransformer(Criteria.ROOT_ENTITY);
		}
		if (orders != null) {
			for (Order order : orders) {
				crit.addOrder(order);
			}
		}
		//p.getFirstResult()---> p.getFirst()
		crit.setFirstResult(p.getFirst());
		crit.setMaxResults(p.getPageSize());
		//p.setList--->p.setResult
		p.setResult(crit.list());
		return p;
	}

	/**
	 * 按id获取对象.
	 */
	public T get(final PK id) {
		return (T) getSession().load(entityClass, id);
	}

	/**
	 * 按属性查找对象列表.
	 */
	public List<T> findByProperty(final String propertyName, final Object value) {
		Assert.hasText(propertyName);
		return createCriteria(Restrictions.eq(propertyName, value)).list();
	}

	/**
	 * 按属性查找唯一对象.
	 */
	public T findUniqueByProperty(final String propertyName, final Object value) {
		Assert.hasText(propertyName);
		return (T) createCriteria(Restrictions.eq(propertyName, value)).uniqueResult();
	}

	/**
	 * 按HQL查询对象列表.
	 * 
	 * @param hql hql语句
	 * @param values 数量可变的参数
	 */
	public List find(final String hql, final Object... values) {
		return createQuery(hql, values).list();
	}

	/**
	 * 按HQL分页查询.
	 * 不支持自动获取总结果数,需用户另行执行查询.
	 * 
	 * @param page 分页参数.仅支持pageSize 和firstResult,忽略其他参数.
	 * @param hql hql语句.
	 * @param values 数量可变的查询参数.
	 * 
	 * @return 分页查询结果,附带结果列表及所有查询时的参数.
	 */
	@SuppressWarnings("unchecked")
	public Page<T> find(final Page<T> page, final String hql, final Object... values) {
		Assert.notNull(page);
		if (page.isAutoCount()) {
			logger.warn("HQL查询暂不支持自动获取总结果数,hql语句为{}", hql);
		}

		Query q = createQuery(hql, values);
		pagationQuery(q, page);
		List result = q.list();
		page.setResult(result);
		return page;
	}
	
	/**
	* 设置分页参数到Query对象,辅助函数.
	*/
	protected Query pagationQuery(final Query q, final PageRequest page) {
		q.setFirstResult(page.getFirst());
		q.setMaxResults(page.getPageSize());
		return q;
	}

	/**
	 * 按HQL查询唯一对象.
	 */
	public Object findUnique(final String hql, final Object... values) {
		return createQuery(hql, values).uniqueResult();
	}

	/**
	 * 按HQL查询Integer类型结果. 
	 */
	public Integer findInt(final String hql, final Object... values) {
		return (Integer) findUnique(hql, values);
	}

	/**
	 * 按HQL查询Long类型结果. 
	 */
	public Long findLong(final String hql, final Object... values) {
		return (Long) findUnique(hql, values);
	}

	/**
	 * 按Criterion查询对象列表.
	 * 
	 * @param criterion 数量可变的Criterion.
	 */
	public List<T> findByCriteria(final Criterion... criterion) {
		return createCriteria(criterion).list();
	}

	/**
	 * 按Criteria分页查询.
	 * 
	 * @param page 分页参数.支持pageSize、firstResult和orderBy、order、autoCount参数.
	 *             其中autoCount指定是否动态获取总结果数.         
	 * @param criterions 数量可变的Criterion.
	 * 
	 * @return 分页查询结果.附带结果列表及所有查询时的参数.
	 */
	@SuppressWarnings("unchecked")
	public Page<T> findByCriteria(final Page<T> page, final Criterion... criterions) {
		Assert.notNull(page);

		Criteria c = createCriteria(criterions);

		if (page.isAutoCount()) {
			int totalCount = countCriteriaResult(c, page);
			page.setTotalCount(totalCount);
		}

		pagationCriteria(c, page);
		List result = c.list();
		page.setResult(result);
		return page;
	}
	
	/**
	 * 设置分页参数到Criteria对象,辅助函数.
	 */
	protected Criteria pagationCriteria(final Criteria c, final PageRequest page) {
		c.setFirstResult(page.getFirst());
		c.setMaxResults(page.getPageSize());

		if (page.isOrderBySetted()) {
			String[] orderByArray = StringUtils.split(page.getOrderBy(), ',');
			String[] orderArray = StringUtils.split(page.getOrder(), ',');

			Assert.isTrue(orderByArray.length != orderArray.length, "分页排序参数中,排序字段与排序方向的个数不相等");

			for (int i = 0; i < orderByArray.length; i++) {
				if (PageRequest.ASC.equals(orderArray[i])) {
					c.addOrder(Order.asc(orderByArray[i]));
				} else {
					c.addOrder(Order.desc(orderByArray[i]));
				}
			}
		}
		return c;
	}
	
	/**
	 * 执行count查询获得本次Criteria查询所能获得的对象总数.
	 * 
	 * @return page对象中的totalCount属性将赋值.
	 */
	@SuppressWarnings("unchecked")
	protected int countCriteriaResult(final Criteria c, final PageRequest page) {
		CriteriaImpl impl = (CriteriaImpl) c;

		// 先把Projection、ResultTransformer、OrderBy取出来,清空三者后再执行Count操作
		Projection projection = impl.getProjection();
		ResultTransformer transformer = impl.getResultTransformer();

		List<CriteriaImpl.OrderEntry> orderEntries = null;
		try {
			orderEntries = (List) ReflectionUtils.getFieldValue(impl, "orderEntries");
			ReflectionUtils.setFieldValue(impl, "orderEntries", new ArrayList());
		} catch (Exception e) {
			logger.error("不可能抛出的异常:{}", e.getMessage());
		}

		// 执行Count查询
		int totalCount = (Integer) c.setProjection(Projections.rowCount()).uniqueResult();

		// 将之前的Projection,ResultTransformer和OrderBy条件重新设回去
		c.setProjection(projection);

		if (projection == null) {
			c.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
		}
		if (transformer != null) {
			c.setResultTransformer(transformer);
		}

		try {
			ReflectionUtils.setFieldValue(impl, "orderEntries", orderEntries);
		} catch (Exception e) {
			logger.error("不可能抛出的异常:{}", e.getMessage());
		}

		return totalCount;
	}
	
	//下面增加一个findBy 方法------> 来自jeecms
	/**
	 * 来自jeecms
	 * 修改方法类型：protected----> public
	 * 修改参数: 参数前面全部增加：final
	 * 修改类Pagination------>Page<T>
	 * 增加Finder 类
	 */
	@SuppressWarnings("unchecked")
	public Page<T> findByFinder(final Finder finder, final int pageNo, final int pageSize) {
		int totalCount = countQueryResult(finder);
		//修改这个构造函数
		Page p = new Page(pageNo, pageSize, totalCount);
		if (totalCount < 1) {
			//p.setList--->p.setResult
			p.setResult(new ArrayList());
			return p;
		}
		Query query = getSession().createQuery(finder.getOrigHql());
		finder.setParamsToQuery(query);
		//p.getFirstResult()--->
		query.setFirstResult(p.getFirst());
		query.setMaxResults(p.getPageSize());
		List list = query.list();
		//p.setList--->p.setResult
		p.setResult(list);
		return p;
	}
	/**
	 * 来自jeecms
	 * 修改方法类型：protected----> public
	 * 修改参数: 参数前面全部增加：final
	 * 修改类
	 * 增加Finder 类
	 */
	 @SuppressWarnings("unchecked")
	public List<T> findByFinder(final Finder finder) {
		int totalCount = countQueryResult(finder);
		if (totalCount < 1) {
			return new ArrayList();
		}
		Query query = getSession().createQuery(finder.getOrigHql());
		finder.setParamsToQuery(query);
		query.setFirstResult(finder.getFirstResult());
		query.setMaxResults(finder.getMaxResults());
		List list = query.list();
		return list;
	}
	/**
	 * 来自jeecms
	 * 修改方法类型：protected----> public
	 * 修改参数: 参数前面全部增加：final
	 * 修改类
	 * 增加Finder 类
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByEgList(final T eg, boolean anyWhere, final Condition[] conds,
			String... exclude) {
		Criteria crit = getCritByEg(eg, anyWhere, conds, exclude);
		return crit.list();
	}

	/**
	 * 来自jeecms
	 * 修改方法类型：protected----> public
	 * 修改参数: 参数前面全部增加：final
	 * 修改类
	 * 增加Finder 类
	 */
	@SuppressWarnings("unchecked")
	public List<T> findByEgList(final T eg, final boolean anyWhere, final Condition[] conds,
			int firstResult, int maxResult, String... exclude) {
		Criteria crit = getCritByEg(eg, anyWhere, conds, exclude);
		crit.setFirstResult(firstResult);
		crit.setMaxResults(maxResult);
		return crit.list();
	}

	/**
	 * 来自jeecms
	 * 修改方法类型：protected----> public
	 * 修改参数: 参数前面全部增加：final
	 * 修改类Pagination---Page<T>
	 * 增加Finder 类
	 * 
	 */
	public Page<T> findByEg(final T eg, final boolean anyWhere, final Condition[] conds,
			int page, int pageSize, String... exclude) {
		Criteria crit = getCritByEg(eg, anyWhere, conds, exclude);
		return findByCriteria(crit, page, pageSize, null);
	}
	
	/**
	 * 来自jeecms
	 * 修改方法类型：protected----> public
	 * 修改参数: 参数前面全部增加：final
	 * 修改类:getPersistentClass()----->entityClass
	 * 增加Finder 类
	 */
	public Criteria getCritByEg(final T bean, final boolean anyWhere, final Condition[] conds,
			String... exclude) {
		Criteria crit = getSession().createCriteria(entityClass);
		Example example = Example.create(bean);
		example.setPropertySelector(NOT_BLANK);
		if (anyWhere) {
			example.enableLike(MatchMode.ANYWHERE);
			example.ignoreCase();
		}
		for (String p : exclude) {
			example.excludeProperty(p);
		}
		crit.add(example);
		// 处理排序和is null字段
		if (conds != null) {
			for (Condition o : conds) {
				if (o instanceof OrderBy) {
					OrderBy order = (OrderBy) o;
					crit.addOrder(order.getOrder());
				} else if (o instanceof Nullable) {
					Nullable isNull = (Nullable) o;
					if (isNull.isNull()) {
						crit.add(Restrictions.isNull(isNull.getField()));
					} else {
						crit.add(Restrictions.isNotNull(isNull.getField()));
					}
				} else {
					// never
				}
			}
		}
		// 处理many to one查询
		ClassMetadata cm = getCmd(bean.getClass());
		String[] fieldNames = cm.getPropertyNames();
		for (String field : fieldNames) {
			Object o = cm.getPropertyValue(bean, field, POJO);
			if (o == null) {
				continue;
			}
			ClassMetadata subCm = getCmd(o.getClass());
			if (subCm == null) {
				continue;
			}
			Serializable id = subCm.getIdentifier(o, POJO);
			if (id != null) {
				Serializable idName = subCm.getIdentifierPropertyName();
				crit.add(Restrictions.eq(field + "." + idName, id));
			} else {
				crit.createCriteria(field).add(Example.create(o));
			}
		}
		return crit;
	}
	
	/**
	 * 来自jeecms
	 * 修改方法类型：protected----> public
	 * 修改参数: 参数前面全部增加：final
	 */
	public void refresh(Object entity) {
		getSession().refresh(entity);
	}
	/**
	 * 来自：jeecms
	 * 
	 * @param updater
	 * @param po
	 */
	public Object updateDefault(Object entity) {
		return updateByUpdater(Updater.create(entity));
	}
	/**
	 * 来自：jeecms
	 * 
	 * @param updater
	 * @param po
	 */
	public Object updateByUpdater(Updater updater) {
		ClassMetadata cm = getCmd(updater.getBean().getClass());
		if (cm == null) {
			throw new RuntimeException("所更新的对象没有映射或不是实体对象");
		}
		Object bean = updater.getBean();
		Object po = getSession().load(bean.getClass(),
				cm.getIdentifier(bean, POJO));
		updaterCopyToPersistentObject(updater, po);
		return po;
	}

	/**
	 * 来自：jeecms
	 * 将更新对象拷贝至实体对象，并处理many-to-one的更新。
	 * 
	 * @param updater
	 * @param po
	 */
	@SuppressWarnings("unchecked")
	private void updaterCopyToPersistentObject(Updater updater, Object po) {
		Map map = MyBeanUtils.describe(updater.getBean());
		Set<Map.Entry<String, Object>> set = map.entrySet();
		for (Map.Entry<String, Object> entry : set) {
			String name = entry.getKey();
			Object value = entry.getValue();
			if (!updater.isUpdate(name, value)) {
				continue;
			}
			if (value != null) {
				Class valueClass = value.getClass();
				ClassMetadata cm = getCmd(valueClass);
				if (cm != null) {
					Serializable vid = cm.getIdentifier(value, POJO);
					// 如果更新的many to one的对象的id为空，则将many to one设置为null。
					if (vid != null) {
						value = getSession().load(valueClass, vid);
					} else {
						value = null;
					}
				}
			}
			try {
				PropertyUtils.setProperty(po, name, value);
			} catch (Exception e) {
				// never
				logger.warn("更新对象时，拷贝属性异常", e);
			}
		}
	}



	/**
	 * 根据查询HQL与参数列表创建Query对象,辅助函数.
	 */
	public Query createQuery(final String queryString, final Object... values) {
		Assert.hasText(queryString);
		Query queryObject = getSession().createQuery(queryString);
		if (values != null) {
			for (int i = 0; i < values.length; i++) {
				queryObject.setParameter(i, values[i]);
			}
		}
		return queryObject;
	}

	/**
	 * 根据Criterion条件创建Criteria,辅助函数.
	 */
	public Criteria createCriteria(final Criterion... criterions) {
		Criteria criteria = getSession().createCriteria(entityClass);
		for (Criterion c : criterions) {
			criteria.add(c);
		}
		return criteria;
	}

	/**
	 * 判断对象的属性值在数据库内是否唯一.
	 * 
	 * 在修改对象的情景下,如果属性新修改的值(value)等于属性原来的值(orgValue)则不作比较.
	 * 相对于SS2里那种以对象ID作为第3个参数查找数据库中原属性值的做法，以orgValue做第3个参数的做法侧重于从页面上发出Ajax判断请求的场景.
	 */
	public boolean isPropertyUnique(final String propertyName, final Object newValue, final Object orgValue) {
		if (newValue == null || newValue.equals(orgValue))
			return true;

		Object object = findUniqueByProperty(propertyName, newValue);
		return (object == null);
	}

	/**
	 * 增加来自jeecms
	 * 通过count查询获得本次查询所能获得的对象总数.
	 * 要增加Finder 这个类
	 * 修改参数为：Finder finder ---- final Finder finder
	 * @param finder
	 * @return
	 */
	protected int countQueryResult(final Finder finder) {
		Query query = getSession().createQuery(finder.getRowCountHql());
		finder.setParamsToQuery(query);
		return ((Number) query.iterate().next()).intValue();
	}
	/**
	 * 增加来自jeecms
	 * 通过count查询获得本次查询所能获得的对象总数.
	 * 要增加Finder 这个类
	 * 修改参数为：
	 * @param getPersistentClass()---- > entityClass
	 * @return
	 */
	public T createNewEntiey() {
		try {
			return entityClass.newInstance();
		} catch (Exception e) {
			throw new RuntimeException("不能创建实体对象："
					+ entityClass.getName());
		}
	}
	/**
	 * 增加来自jeecms
	 * 通过count查询获得本次查询所能获得的对象总数.
	 * 要增加Finder 这个类
	 * 修改参数为：
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private ClassMetadata getCmd(Class clazz) {
		return (ClassMetadata) sessionFactory.getClassMetadata(clazz);
	}
	//增加来自jeecms
	public static final NotBlankPropertySelector NOT_BLANK = new NotBlankPropertySelector();

	/**
	 * 增加来自jeecms
	 * 不为空的EXAMPLE属性选择方式
	 * 
	 * @author liufang
	 * 
	 */
	static final class NotBlankPropertySelector implements PropertySelector {
		private static final long serialVersionUID = 1L;

		public boolean include(Object object, String propertyName, Type type) {
			return object != null
					&& !(object instanceof String && StringUtils
							.isBlank((String) object));
		}
	}

	
	/**
	 * 增加来自jeecms
	 * 通过count查询获得本次查询所能获得的对象总数.
	 * protected -------> public
	 * @return page对象中的totalCount属性将赋值.
	 */
	@SuppressWarnings("unchecked")
	protected int countQueryResult(Criteria c) {
		CriteriaImpl impl = (CriteriaImpl) c;
		// 先把Projection、ResultTransformer、OrderBy取出来,清空三者后再执行Count操作
		Projection projection = impl.getProjection();
		ResultTransformer transformer = impl.getResultTransformer();
		List<CriteriaImpl.OrderEntry> orderEntries = null;
		try {
			orderEntries = (List) MyBeanUtils.getFieldValue(impl,
					"orderEntries");
			MyBeanUtils.setFieldValue(impl, "orderEntries", new ArrayList());
		} catch (Exception e) {
			logger.error("不可能抛出的异常:{}", e.getMessage());
		}
		// 执行Count查询
		int totalCount = (Integer) c.setProjection(Projections.rowCount())
				.uniqueResult();
		if (totalCount < 1) {
			return 0;
		}
		// 将之前的Projection和OrderBy条件重新设回去
		c.setProjection(projection);
		if (projection == null) {
			c.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
		}
		if (transformer != null) {
			c.setResultTransformer(transformer);
		}
		try {
			MyBeanUtils.setFieldValue(impl, "orderEntries", orderEntries);
		} catch (Exception e) {
			logger.error("不可能抛出的异常:{}", e.getMessage());
		}
		return totalCount;
	}
	

	/**
	 * 执行count查询获得本次查询所能获得的对象总数.
	 * 
	 * @return page对象中的totalCount属性将赋值.
	 */
	protected int countQueryResult(final Page<T> page, final Criteria c) {
		CriteriaImpl impl = (CriteriaImpl) c;

		// 先把Projection、ResultTransformer、OrderBy取出来,清空三者后再执行Count操作
		Projection projection = impl.getProjection();
		ResultTransformer transformer = impl.getResultTransformer();

		List<CriteriaImpl.OrderEntry> orderEntries = null;
		try {
			orderEntries = (List) ReflectionUtils.getFieldValue(impl, "orderEntries");
			ReflectionUtils.setFieldValue(impl, "orderEntries", new ArrayList());
		} catch (Exception e) {
			logger.error("不可能抛出的异常:{}", e.getMessage());
		}

		// 执行Count查询
		int totalCount = (Integer) c.setProjection(Projections.rowCount()).uniqueResult();

		// 将之前的Projection和OrderBy条件重新设回去
		c.setProjection(projection);

		if (projection == null) {
			c.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
		}
		if (transformer != null) {
			c.setResultTransformer(transformer);
		}

		try {
			ReflectionUtils.setFieldValue(impl, "orderEntries", orderEntries);
		} catch (Exception e) {
			logger.error("不可能抛出的异常:{}", e.getMessage());
		}

		return totalCount;
	}
}